/* 

1 不要轻易的在 定时器内 去操作 state的数据 
  1 setState代码异步 
  2 setInterval 内部 开启了闭包！ 
    闭包就记住了 开始 second的数值 0 
2 react官方也知道 提供了第二种 修改state的写法 
  setState 接收一个函数-形参-state。返回新的数据->state中



*/

/* 
 1 autoFocus 自动获得焦点 
 2 autoComplete="off"    表单标签的历史输入记录    
    1 on 打开  off 关闭
    2 这个属性也可以添加到 form标签上 来控制form标签里面所有的input 
  3 输入文字格式 maxLength 

 */
import NavBar from "@/components/NavBar";
import styles from "./index.module.scss";

import Input from "@/components/Input";

import { useFormik } from "formik";
// 导入 Yup
import * as Yup from "yup";
import { useEffect, useRef, useState } from "react";
// 引入action
import { loginAction, sendCodes } from "@/store/action/user";
import { useAppDispatch } from "@/hooks";
import { Toast } from "antd-mobile";
import { useHistory } from "react-router-dom";

// 类型登录表单的类型
type LoginFormType = {
  mobile: string;
  code: string;
};

export default function Login() {
  const history = useHistory();

  const search = history.location.search; // ?from=abc
  const usp = new URLSearchParams(search);
  const from = usp.get("from") || "/"; // 如果用户一打开的页面就是 登录的话，此时from null
  // console.log(from); // 输出来源页面

  // 时间
  const [second, setSecond] = useState(0);
  // 获取dispatch
  const dispatch = useAppDispatch();

  // 定义表单验证 函数
  // const validate = (values: LoginFormType) => {
  //   // as 断言 明确它的类型是 LoginFormType
  //   const errors = {} as LoginFormType;
  //   if (!values.mobile) {
  //     errors.mobile = "手机号码必填";
  //   }
  //   if (!values.code) {
  //     errors.code = "验证码必填";
  //   }
  //   return errors;
  // };

  // 初始化数据和时间
  const formik = useFormik({
    initialValues: {
      mobile: "15656787654",
      code: "",
    },
    // 使用验证函数  旧的方式
    // validate,
    // 新的 利用 yup库的方式   创建 表单验证 数据结构
    validationSchema: Yup.object().shape({
      // 非空和手机号码
      mobile: Yup.string()
        .required("手机号码必填")
        .matches(/^1(3|4|5|7|8)\d{9}$/, "手机号码格式不对"),
      // 非空和6位数
      code: Yup.string()
        .required("验证码必填")
        .matches(/^\d{6}$/, "6位数"),
    }),
    onSubmit: async (values) => {
      /* 
      1 获取表单的手机号码和验证码 
      2 发送给后端 完成登录  
       */
      // console.log(values);

      await dispatch(loginAction(values));

      Toast.show({ content: "登录成功" });

      // 跳转页面
      // from
      // console.log(from);

      history.replace(from);
    },
  });

  /* 
  问题：
  1 formik.isValid 在一打开页面的时候 值 true  和 实际要求不符合 - 希望一开始为false 
  
  思考
  1 dirty   脏！  理解 你是否操作过表达 如果是 true ，否则就是false 

  2 formik.isValid 和  formik.dirty 结合 实现我们要的效果 

  3 disabled={!formik.isValid}

  4 判断的条件 
    1 用户操作过页面 脏 formik.dirty    = true
    2 表单验证通过 formik.isValid = true
  
  5  3 disabled={ !(formik.isValid&&formik.dirty) }
       两个都为true  就不要(!)  禁用按钮 (disabled)
    
   */
  // console.log(formik);

  // 定时器id 默认值  state  useRef
  // let timeId = -1;
  const ref = useRef(-1);

  // 验证码相关的业务
  const handleSendCodes = async () => {
    // 通过的dispatch 来触发 调用接口 获取手机验证码
    await dispatch(sendCodes(formik.values.mobile));

    // 弹出提示
    Toast.show({ content: "发送验证码成功" });

    // 设置为 60秒
    setSecond(60); //  setSecond 异步  setState 异步！！
    // console.log(second); // 还是原来的样子  0

    // 停止定时器 坑 ❤    加上 window 即可
    ref.current = window.setInterval(() => {
      // console.log("定时器执行");

      // ❤❤❤❤
      // setSecond(second - 1);
      // console.log(second);

      // 新的写法
      setSecond((s) => {
        // 只要在这位置 才能拿到 真实的数据  s
        if (s === 1) {
          // 停止定时器
          clearInterval(ref.current);
          // console.log("停止定时器");
        }
        return s - 1;
      });
    }, 1000);
  };

  // 当页面卸载了 停止定时器
  useEffect(() => {
    return () => {
      //  停止定时器
      clearInterval(ref.current);
    };
  }, []);

  return (
    <div className={styles.root}>
      <NavBar>登录</NavBar>
      <div className="content">
        {/* 标题 */}
        <h3>短信登录</h3>
        <form onSubmit={formik.handleSubmit}>
          {/* 手机号输入框 */}
          <div className="input-item">
            <Input
              value={formik.values.mobile}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              autoFocus
              className="input"
              placeholder="请输入手机号"
              type="text"
              name="mobile"
              autoComplete="off"
              maxLength={11}
              errorMsg={
                formik.touched.mobile && formik.errors.mobile
                  ? formik.errors.mobile
                  : ""
              }
            />
          </div>

          {/* 短信验证码输入框 */}
          <div className="input-item">
            <Input
              value={formik.values.code}
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              className="input"
              placeholder="请输入验证码"
              type="text"
              name="code"
              autoComplete="off"
              maxLength={6}
              errorMsg={
                formik.touched.code && formik.errors.code
                  ? formik.errors.code
                  : ""
              }
              extra={
                second === 0 ? (
                  <span onClick={handleSendCodes}>获取验证码</span>
                ) : (
                  `还剩余${second}秒`
                )
              }
            />
          </div>

          {/* 登录按钮 */}
          <button
            type="submit"
            className="login-btn"
            disabled={!(formik.isValid && formik.dirty)}
          >
            登录
          </button>
        </form>
      </div>
    </div>
  );
}
